package com.example.demo.config;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

import javax.servlet.Filter;

import org.apache.shiro.session.mgt.DefaultSessionManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager; 
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.example.demo.shiro.ShiroSimpleRealm;
import lombok.extern.log4j.Log4j2;
import com.example.demo.shiro.ShiroSimpleSessionManager;
import com.example.demo.shiro.ShiroSimpleAuthenticationFilter;

/**
 * Shiro 权限控制配置类
 * @author Administrator
 *
 */
@Log4j2
@Configuration
public class ShiroConfig {

    //Session过期时间	
	@Value("${demo-settings.SessionTimeout}")
    private long sessionTimeout = 30 * 60 * 1000;
    
//    @Value("${demo-settings.SessionTimeout}")
//    public void setSessionTimeout(Long sessionTimeout) {
//    	this.sessionTimeout=sessionTimeout;
//    }
	
	/**
	 * 将自己的验证方式加入容器
	 * @return
	 */
    @Bean(name = "shiroRealm")
    public ShiroSimpleRealm shiroRealm() {
        ShiroSimpleRealm shiroRealm = new ShiroSimpleRealm();
//        shiroRealm.setCacheManager(cacheManager);
        return shiroRealm;
    }
    
    /**
     * 将自己的Session Manager 加入容器
     * @return
     */
    @Bean(name="sessionManager")
    public SessionManager sessionManager() {
    	DefaultWebSessionManager sessionManager=new ShiroSimpleSessionManager();
//    	sessionManager.getSessionIdCookie().setDomain(""); //设置cookie 域
//    	sessionManager.getSessionIdCookie().setPath(""); //设置cookie 路径
    	sessionManager.setGlobalSessionTimeout(sessionTimeout);
    	System.out.println("Session过期时间:"+sessionTimeout+" 毫秒后");
    	log.info("Session过期时间:"+sessionTimeout+" 毫秒后");
    	sessionManager.setSessionValidationSchedulerEnabled(true);
    	sessionManager.setSessionIdUrlRewritingEnabled(false);      	
    	return sessionManager;
    }
    
    /**
     * 权限管理，配置主要是Realm的管理认证
     * @return
     */
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setSessionManager(sessionManager());
        securityManager.setRealm(shiroRealm());
        return securityManager;
    }
    
    /**
     * Filter工厂，设置对应的过滤条件和跳转条件
     * @param securityManager
     * @return
     */
    @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean shiroFilter(org.apache.shiro.mgt.SecurityManager securityManager) {
    	 
    	 ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
         shiroFilterFactoryBean.setSecurityManager(securityManager);
         Map<String,String> filterChainDefinitionMap = new HashMap<String, String>();         

         //自定义拦截器
         Map<String, Filter> filtersMap = new LinkedHashMap<String, Filter>();
         filtersMap.put("SimpleFormAuthenticationFilter", ShiroSimpleAuthenticationFilter());  

         //静态资源
         filterChainDefinitionMap.put("/static/**","anon");
         //登陆退出模块
         filterChainDefinitionMap.put("/security/**","anon");
         //登录页面
         filterChainDefinitionMap.put("/login.html","anon");
         //登出页面
         filterChainDefinitionMap.put("/logout.html","logout");
         
         //上传文件接口 解决跨域上传文件被 shiro 拦截 内部做登陆权限验证
         filterChainDefinitionMap.put("/base/media/upload", "anon");
         
         //对所有用户认证
         filterChainDefinitionMap.put("/**","authc");
         
         //登录
         shiroFilterFactoryBean.setLoginUrl("/login.html");
         //首页
         shiroFilterFactoryBean.setSuccessUrl("/index.html");
         //错误页面，认证不通过跳转
         shiroFilterFactoryBean.setUnauthorizedUrl("/error.html");
         
         shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
         shiroFilterFactoryBean.setFilters(filtersMap);
         
         return shiroFilterFactoryBean;
    }
    
//    /**
//     * 
//     * @return
//     */
//    @Bean
//    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
//    	DefaultAdvisorAutoProxyCreator proxyCreator=new DefaultAdvisorAutoProxyCreator();
//    	proxyCreator.setProxyTargetClass(true);
//    	return proxyCreator;
//    }  
    
    /**
     * 配置Shiro生命周期处理器
     * 使用springboot整合shiro时，@value注解无法读取application.yml中的配置
     *解决方法:将LifecycleBeanPostProcessor的配置方法改成静态的就可以了
      *LifecycleBeanPostProcessor将Initializable和Destroyable的实现类统一在其内部自动分别调用了Initializable.init()和Destroyable.destroy()方法，从而达到管理shiro bean生命周期的目的
    */
    @Bean(name = "lifecycleBeanPostProcessor")
    public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    } 
    
    /**
     * 开启 SHIRO AOP 注解支持
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(org.apache.shiro.mgt.SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
    
    /**
           * 自定义过滤器 ---》处理AJAX 请求无权限时返厍401 状态码
     * @return
     */
    @Bean("ShiroSimpleAuthenticationFilter")
    public ShiroSimpleAuthenticationFilter ShiroSimpleAuthenticationFilter() {
        return new ShiroSimpleAuthenticationFilter();
    }
    
    
}
